package de.ubschmidt.capi;

import java.nio.ByteBuffer;

/**
 *
 */
public enum Command
        implements ByteBufferWritable {

    ALERT_REQ(0x01, 0x80),
    ALERT_CONF(0x01, 0x81),
    CONNECT_REQ(0x02, 0x80),
    CONNECT_CONF(0x02, 0x81),
    CONNECT_IND(0x02, 0x82),
    CONNECT_RESP(0x02, 0x83),
    CONNECT_ACTIVE_IND(0x03, 0x82),
    CONNECT_ACTIVE_RESP(0x03, 0x83),
    CONNECT_B3_ACTIVE_IND(0x83, 0x82),
    CONNECT_B3_ACTIVE_RESP(0x83, 0x83),
    CONNECT_B3_REQ(0x82, 0x80),
    CONNECT_B3_CONF(0x82, 0x81),
    CONNECT_B3_IND(0x82, 0x82),
    CONNECT_B3_RESP(0x82, 0x83),
    CONNECT_B3_T90_ACTIVE_IND(0x88, 0x82),
    CONNECT_B3_T90_ACTIVE_RESP(0x88, 0x83),
    DATA_B3_REQ(0x86, 0x80),
    DATA_B3_CONF(0x86, 0x81),
    DATA_B3_IND(0x86, 0x82),
    DATA_B3_RESP(0x86, 0x83),
    DISCONNECT_B3_REQ(0x84, 0x80),
    DISCONNECT_B3_CONF(0x84, 0x81),
    DISCONNECT_B3_IND(0x84, 0x82),
    DISCONNECT_B3_RESP(0x84, 0x83),
    DISCONNECT_REQ(0x04, 0x80),
    DISCONNECT_CONF(0x04, 0x81),
    DISCONNECT_IND(0x04, 0x82),
    DISCONNECT_RESP(0x04, 0x83),
    FACILITY_REQ(0x80, 0x80),
    FACILITY_CONF(0x80, 0x81),
    FACILITY_IND(0x80, 0x82),
    FACILITY_RESP(0x80, 0x83),
    INFO_REQ(0x08, 0x80),
    INFO_CONF(0x08, 0x81),
    INFO_IND(0x08, 0x82),
    INFO_RESP(0x08, 0x83),
    LISTEN_REQ(0x05, 0x80),
    LISTEN_CONF(0x05, 0x81),
    MANUFACTURER_REQ(0xff, 0x80),
    MANUFACTURER_CONF(0xff, 0x81),
    MANUFACTURER_IND(0xff, 0x82),
    MANUFACTURER_RESP(0xff, 0x83),
    RESET_B3_REQ(0x87, 0x80),
    RESET_B3_CONF(0x87, 0x81),
    RESET_B3_IND(0x87, 0x82),
    RESET_B3_RESP(0x87, 0x83),
    SELECT_B_PROTOCOL_REQ(0x41, 0x80),
    SELECT_B_PROTOCOL_CONF(0x41, 0x81);

    /**
     * Define a new {@code Command} enum with the specified {@code commandByte}
     * and {@code subCommandByte}.
     *
     * @param commandByte The first byte of the command.
     * @param subCommandByte The second byte of the command.
     */
    Command(final int commandByte, final int subCommandByte) {
        _commandByte = (byte) commandByte;
        _subCommandByte = (byte) subCommandByte;
    }

    /**
     * Retrieve the command byte of this {@code Command}.
     *
     * @return The command byte.
     */
    public byte getCommandByte() {
        return _commandByte;
    }

    /**
     * Retrieve the subcommand byte of this {@code Command}.
     *
     * @return The subcommand byte.
     */
    public byte getSubCommandByte() {
        return _subCommandByte;
    }

    /**
     * Lookup the {@code Command} which matches the specified
     * commandByte and subCommandByte.
     */
    public static Command valueOf(final byte commandByte,
            final byte subCommandByte) {
        for (Command c : values()) {
            if (c.getCommandByte() == commandByte
                    && c.getSubCommandByte() == subCommandByte) {
                return c;
            }
        }

        throw new IllegalArgumentException("no such Command");
    }

    /** {@inheritDoc} */
    public void writeTo(final ByteBuffer byteBuffer) {
        byteBuffer.put(getCommandByte());
        byteBuffer.put(getSubCommandByte());
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        return String.format("%s(0x%02x, 0x%02x)",
                name(), getCommandByte(), getSubCommandByte());
    }

    private byte _commandByte;
    private byte _subCommandByte;

}
